home *** CD-ROM | disk | FTP | other *** search
/ BCI NET / BCI NET Dec 94.iso / archives / programming / languages / ami_nuweb0.87c.lha / names.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-12  |  12.5 KB  |  404 lines

  1. #include "global.h"
  2. enum { LESS, GREATER, EQUAL, PREFIX, EXTENSION };
  3.  
  4. static int compare(char *x, char *y)
  5. {
  6.   int len, result;
  7.   int xl = strlen(x);
  8.   int yl = strlen(y);
  9.   int xp = x[xl - 1] == ' ';
  10.   int yp = y[yl - 1] == ' ';
  11.   if (xp) xl--;
  12.   if (yp) yl--;
  13.   len = xl < yl ? xl : yl;
  14.   result = strncmp(x, y, len);
  15.   if (result < 0) return GREATER;
  16.   else if (result > 0) return LESS;
  17.   else if (xl < yl) {
  18.     if (xp) return EXTENSION;
  19.     else return LESS;
  20.   }
  21.   else if (xl > yl) {
  22.     if (yp) return PREFIX;
  23.     else return GREATER;
  24.   }
  25.   else return EQUAL;
  26. } char *save_string(char *s)
  27. {
  28.   char *new = (char *) arena_getmem((strlen(s) + 1) * sizeof(char));
  29.   strcpy(new, s);
  30.   return new;
  31. } static int ambiguous_prefix(Name *, char *);
  32.  
  33. Name *prefix_add(Name **root, char *spelling)
  34. {
  35.   Name *node = *root;
  36.   while (node) {
  37.     switch (compare(node->spelling, spelling)) {
  38.     case GREATER:   root = &node->rlink;
  39.                     break;
  40.     case LESS:      root = &node->llink;
  41.                     break;
  42.     case EQUAL:     return node;
  43.     case EXTENSION: node->spelling = save_string(spelling);
  44.                     return node;
  45.     case PREFIX:    {
  46.                       if (ambiguous_prefix(node->llink, spelling) ||
  47.                           ambiguous_prefix(node->rlink, spelling))
  48.                     #ifdef _AMIGA
  49.                         fprintf(stderr, get_string(MSG_WARNING_56B),
  50.                     #else
  51.                         fprintf(stderr,
  52.                                 "%s: ambiguous prefix @<%s...@> (%s, line %d)\n",
  53.                     #endif
  54.                                 command_name, spelling, source_name, source_line);
  55.                     }
  56.                     return node;
  57.     }
  58.     node = *root;
  59.   }
  60.   {
  61.     node = (Name *) arena_getmem(sizeof(Name));
  62.     node->spelling = save_string(spelling);
  63.     node->mark = FALSE;
  64.     node->llink = NULL;
  65.     node->rlink = NULL;
  66.     node->uses = NULL;
  67.     node->defs = NULL;
  68.     node->tab_flag = TRUE;
  69.     node->indent_flag = TRUE;
  70.     node->debug_flag = FALSE;
  71.     *root = node;
  72.     return node;
  73.   }
  74. } static int ambiguous_prefix(Name *node, char *spelling)
  75. {
  76.   while (node) {
  77.     switch (compare(node->spelling, spelling)) {
  78.     case GREATER:   node = node->rlink;
  79.                     break;
  80.     case LESS:      node = node->llink;
  81.                     break;
  82.     case EQUAL:
  83.     case EXTENSION:
  84.     case PREFIX:    return TRUE;
  85.     }
  86.   }
  87.   return FALSE;
  88. }
  89. static int robs_strcmp(char *x, char *y)
  90. {
  91.   char *xx = x;
  92.   char *yy = y;
  93.   int xc = toupper(*xx);
  94.   int yc = toupper(*yy);
  95.   while (xc == yc && xc) {
  96.     xx++;
  97.     yy++;
  98.     xc = toupper(*xx);
  99.     yc = toupper(*yy);
  100.   }
  101.   if (xc != yc) return xc - yc;
  102.   xc = *x;
  103.   yc = *y;
  104.   while (xc == yc && xc) {
  105.     x++;
  106.     y++;
  107.     xc = *x;
  108.     yc = *y;
  109.   }
  110.   if (isupper(xc) && islower(yc))
  111.     return xc * 2 - (toupper(yc) * 2 + 1);
  112.   if (islower(xc) && isupper(yc))
  113.     return toupper(xc) * 2 + 1 - yc * 2;
  114.   return xc - yc;
  115. } Name *name_add(Name **root, char *spelling)
  116. {
  117.   Name *node = *root;
  118.   while (node) {
  119.     int result = robs_strcmp(node->spelling, spelling);
  120.     if (result > 0)
  121.       root = &node->llink;
  122.     else if (result < 0)
  123.       root = &node->rlink;
  124.     else
  125.       return node;
  126.     node = *root;
  127.   }
  128.   {
  129.     node = (Name *) arena_getmem(sizeof(Name));
  130.     node->spelling = save_string(spelling);
  131.     node->mark = FALSE;
  132.     node->llink = NULL;
  133.     node->rlink = NULL;
  134.     node->uses = NULL;
  135.     node->defs = NULL;
  136.     node->tab_flag = TRUE;
  137.     node->indent_flag = TRUE;
  138.     node->debug_flag = FALSE;
  139.     *root = node;
  140.     return node;
  141.   }
  142. } Name *collect_file_name(void)
  143. {
  144.   Name *new_name;
  145.   char name[100];
  146.   char *p = name;
  147.   int start_line = source_line;
  148.   int c = source_get();
  149.   while (isspace(c))
  150.     c = source_get();
  151.   while (isgraph(c)) {
  152.     *p++ = c;
  153.     c = source_get();
  154.   }
  155.   if (p == name) {
  156. #ifdef _AMIGA
  157.     fprintf(stderr, get_string(MSG_ERROR_59A1),
  158.             command_name, source_name, start_line);
  159. #else
  160.     fprintf(stderr, "%s: expected file name (%s, %d)\n",
  161.             command_name, source_name, start_line);
  162. #endif
  163.     exit(EXIT_FAILURE);
  164.   }
  165.   *p = '\0';
  166.   new_name = name_add(&file_names, name);
  167.   {
  168.     while (1) {
  169.       while (isspace(c))
  170.         c = source_get();
  171.       if (c == '-') {
  172.         c = source_get();
  173.         do {
  174.           switch (c) {
  175.             case 't': new_name->tab_flag = FALSE;
  176.                       break;
  177.             case 'd': new_name->debug_flag = TRUE;
  178.                       break;
  179.             case 'i': new_name->indent_flag = FALSE;
  180.                       break;
  181.   #ifdef _AMIGA
  182.             default : fprintf(stderr, get_string(MSG_WARNING_59B),
  183.   #else
  184.             default : fprintf(stderr, "%s: unexpected per-file flag (%s, %d)\n",
  185.   #endif
  186.                               command_name, source_name, source_line);
  187.                       break;
  188.           }
  189.           c = source_get();
  190.         } while (!isspace(c));
  191.       }
  192.       else break;
  193.     }
  194.   }
  195.   if (c != '@' || source_get() != '{') {
  196. #ifdef _AMIGA
  197.     fprintf(stderr, get_string(MSG_ERROR_59A2),
  198.             command_name, source_name, start_line);
  199. #else
  200.     fprintf(stderr, "%s: expected @{ after file name (%s, %d)\n",
  201.             command_name, source_name, start_line);
  202. #endif
  203.     exit(EXIT_FAILURE);
  204.   }
  205.   return new_name;
  206. } Name *collect_macro_name(void)
  207. {
  208.   char name[100];
  209.   char *p = name;
  210.   int start_line = source_line;
  211.   int c = source_get();
  212.   while (isspace(c))
  213.     c = source_get();
  214.   while (c != EOF) {
  215.     switch (c) {
  216.       case '@':  {
  217.                    c = source_get();
  218.                    switch (c) {
  219.                      case '@': *p++ = c;
  220.                                break;
  221.                      case '{': {
  222.                                  if (p > name && p[-1] == ' ')
  223.                                    p--;
  224.                                  if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  225.                                    p[-3] = ' ';
  226.                                    p -= 2;
  227.                                  }
  228.                                  if (p == name || name[0] == ' ') {
  229.                                #ifdef _AMIGA
  230.                                    fprintf(stderr, get_string(MSG_ERROR_61A),
  231.                                            command_name, source_name, source_line);
  232.                                #else
  233.                                    fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  234.                                            command_name, source_name, source_line);
  235.                                #endif
  236.                                    exit(EXIT_FAILURE);
  237.                                  }
  238.                                  *p = '\0';
  239.                                  return prefix_add(¯o_names, name);
  240.                                }
  241.                  #ifdef _AMIGA
  242.                      default:  fprintf(stderr, get_string(MSG_ERROR_60B),
  243.                                        command_name, c, source_name, start_line);
  244.                  #else
  245.                      default:  fprintf(stderr,
  246.                                        "%s: unexpected @%c in macro name (%s, %d)\n",
  247.                                        command_name, c, source_name, start_line);
  248.                  #endif
  249.                                exit(EXIT_FAILURE);
  250.                    }
  251.                  }
  252.                  break;
  253.       case '\t':
  254.       case ' ':  *p++ = ' ';
  255.                  do
  256.                    c = source_get();
  257.                  while (c == ' ' || c == '\t');
  258.                  break;
  259.       case '\n': {
  260.                    do
  261.                      c = source_get();
  262.                    while (isspace(c));
  263.                    if (c != '@' || source_get() != '{') {
  264.                  #ifdef _AMIGA
  265.                      fprintf(stderr, get_string(MSG_ERROR_61B),
  266.                              command_name, source_name, start_line);
  267.                  #else
  268.                      fprintf(stderr, "%s: expected @{ after macro name (%s, %d)\n",
  269.                              command_name, source_name, start_line);
  270.                  #endif
  271.                      exit(EXIT_FAILURE);
  272.                    }
  273.                    {
  274.                      if (p > name && p[-1] == ' ')
  275.                        p--;
  276.                      if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  277.                        p[-3] = ' ';
  278.                        p -= 2;
  279.                      }
  280.                      if (p == name || name[0] == ' ') {
  281.                    #ifdef _AMIGA
  282.                        fprintf(stderr, get_string(MSG_ERROR_61A),
  283.                                command_name, source_name, source_line);
  284.                    #else
  285.                        fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  286.                                command_name, source_name, source_line);
  287.                    #endif
  288.                        exit(EXIT_FAILURE);
  289.                      }
  290.                      *p = '\0';
  291.                      return prefix_add(¯o_names, name);
  292.                    }
  293.                  }
  294.       default:   *p++ = c;
  295.                  c = source_get();
  296.                  break;
  297.     }
  298.   }
  299. #ifdef _AMIGA
  300.   fprintf(stderr, get_string(MSG_ERROR_60A),
  301.           command_name, source_name, start_line);
  302. #else
  303.   fprintf(stderr, "%s: expected macro name (%s, %d)\n",
  304.           command_name, source_name, start_line);
  305. #endif
  306.   exit(EXIT_FAILURE);
  307.   return NULL;  /* unreachable return to avoid warnings on some compilers */
  308. } Name *collect_scrap_name(void)
  309. {
  310.   char name[100];
  311.   char *p = name;
  312.   int c = source_get();
  313.   while (c == ' ' || c == '\t')
  314.     c = source_get();
  315.   while (c != EOF) {
  316.     switch (c) {
  317.       case '@':  {
  318.                    c = source_get();
  319.                    switch (c) {
  320.                      case '@': *p++ = c;
  321.                                c = source_get();
  322.                                break;
  323.                      case '>': {
  324.                                  if (p > name && p[-1] == ' ')
  325.                                    p--;
  326.                                  if (p - name > 3 && p[-1] == '.' && p[-2] == '.' && p[-3] == '.') {
  327.                                    p[-3] = ' ';
  328.                                    p -= 2;
  329.                                  }
  330.                                  if (p == name || name[0] == ' ') {
  331.                                #ifdef _AMIGA
  332.                                    fprintf(stderr, get_string(MSG_ERROR_61A),
  333.                                            command_name, source_name, source_line);
  334.                                #else
  335.                                    fprintf(stderr, "%s: empty scrap name (%s, %d)\n",
  336.                                            command_name, source_name, source_line);
  337.                                #endif
  338.                                    exit(EXIT_FAILURE);
  339.                                  }
  340.                                  *p = '\0';
  341.                                  return prefix_add(¯o_names, name);
  342.                                }
  343.                      default:  fprintf(stderr,
  344.                                        "%s: unexpected @%c in macro name (%s, %d)\n",
  345.                                        command_name, c, source_name, source_line);
  346.                                exit(EXIT_FAILURE);
  347.                    }
  348.                  }
  349.                  break;
  350.       case '\t':
  351.       case ' ':  *p++ = ' ';
  352.                  do
  353.                    c = source_get();
  354.                  while (c == ' ' || c == '\t');
  355.                  break;
  356.       default:   if (!isgraph(c)) {
  357. #ifdef _AMIGA
  358.                    fprintf(stderr, get_string(MSG_ERROR_62A1),
  359.                            command_name, source_name, source_line);
  360. #else
  361.                    fprintf(stderr,
  362.                            "%s: unexpected character in macro name (%s, %d)\n",
  363.                            command_name, source_name, source_line);
  364. #endif
  365.                    exit(EXIT_FAILURE);
  366.                  }
  367.                  *p++ = c;
  368.                  c = source_get();
  369.                  break;
  370.     }
  371.   }
  372. #ifdef _AMIGA
  373.   fprintf(stderr, get_string(MSG_ERROR_62A2),
  374.           command_name, source_name, source_line);
  375. #else
  376.   fprintf(stderr, "%s: unexpected end of file (%s, %d)\n",
  377.           command_name, source_name, source_line);
  378. #endif
  379.   exit(EXIT_FAILURE);
  380.   return NULL;  /* unreachable return to avoid warnings on some compilers */
  381. } static Scrap_Node *reverse(Scrap_Node *); /* a forward declaration */
  382.  
  383. void reverse_lists(Name *names)
  384. {
  385.   while (names) {
  386.     reverse_lists(names->llink);
  387.     names->defs = reverse(names->defs);
  388.     names->uses = reverse(names->uses);
  389.     names = names->rlink;
  390.   }
  391. } static Scrap_Node *reverse(Scrap_Node *a)
  392. {
  393.   if (a) {
  394.     Scrap_Node *b = a->next;
  395.     a->next = NULL;
  396.     while (b) {
  397.       Scrap_Node *c = b->next;
  398.       b->next = a;
  399.       a = b;
  400.       b = c;
  401.     }
  402.   }
  403.   return a;